package com.cssw.fyzb.busi.service.acct;

import com.cssw.fyzb.busi.util.BizUtil;
import com.cssw.fyzb.busi.util.Bizs;
import com.cssw.fyzb.busi.util.DateUtil;
import com.cssw.fyzb.busi.util.UuidUtil;
import com.cssw.fyzb.core.dao.acct.AcctDao;
import com.cssw.fyzb.core.dao.acct.RedPackDao;
import com.cssw.fyzb.core.dao.system.SysParamDao;
import com.cssw.fyzb.core.dao.user.UserDao;
import com.cssw.fyzb.core.dao.user.UserExtDao;
import com.cssw.fyzb.core.eao.acct.AcctLogEao;
import com.cssw.fyzb.core.eao.acct.LiveRedPackSubEao;
import com.cssw.fyzb.core.eao.acct.RedPackLogEao;
import com.cssw.fyzb.core.mao.live.LiveStatMao;
import com.cssw.fyzb.core.model.dodb.*;
import com.cssw.fyzb.core.model.eos.LiveRedPackSubEo;
import com.cssw.fyzb.core.model.eos.RedPackLogEo;
import com.cssw.fyzb.core.model.vo.acct.RedPackDetailsVo;
import com.cssw.fyzb.core.model.vo.acct.RedPackUser;
import com.cssw.fyzb.core.util.PkgUtil;
import com.ydn.dbframe.plugin.activerecord.Db;
import com.ydn.dbframe.plugin.activerecord.Page;
import com.ydn.simplequeue.SimpleQueue;
import com.ydn.simplequeue.SimpleQueueFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.text.ParseException;
import java.util.*;
import java.util.concurrent.atomic.AtomicReference;

/**
 * @create 2020-12-24 15:23
 */
@Service
public class RedPackServiceImpl implements RedPackService {
    @Autowired
    private RedPackDao redPackDao;

    @Autowired
    private UserDao userDao;

    @Autowired
    private AcctDao acctDao;

    @Autowired
    private UserExtDao userExtDao;

    @Autowired
    private SimpleQueueFactory simpleQueueFactory;

    @Autowired
    private LiveRedPackSubEao liveRedPackSubEao;

    @Autowired
    private RedPackLogEao redPackLogEao;

    @Autowired
    private LiveStatMao liveStatMao;

    @Autowired
    private SysParamDao sysParamDao;

    @Autowired
    private AcctLogEao acctLogEao;

    /*
    @Override
    public void createLiveRedPack(Long userId, Long liveId, Integer num, BigDecimal money, String title) {
        Db.tx(() -> {
            Long redPackId = redPackDao.saveLiveRedPack(userId, liveId, num, money, title);
            // 生成随机金额，目前取平均
//            BigDecimal avg = money.divide(BigDecimal.valueOf(num), 2, BigDecimal.ROUND_HALF_UP);
            List<BigDecimal> redPackMoney = PkgUtil.divide(money, num);

            List<CmfLiveRedPackSub> subs = new ArrayList<>();
            for (int i = 0; i < num; i++) {
                CmfLiveRedPackSub sub = new CmfLiveRedPackSub();
                sub.setRedPackId(redPackId);
                sub.setUserId(userId);
                sub.setMoney(redPackMoney.get(i));
                Date now = new Date();
                sub.setCreateTime(now);
                sub.setDayTime(TimeUtil.getTimeYYMMDD(now));
                subs.add(sub);
            }
            redPackDao.batchLiveRedPackSub(subs);
            //日志记录
            String packType = "2";
            String changeType = "2";
            String tradeType = "BT402";
            String tradeName = "直播红包-发给粉丝";
            redPackDao.addRedPackLog(userId, packType, changeType, money, redPackId.toString(), tradeType, tradeName);
            // 扣果子
            String transferType = "G";
            String busiType = "BT402";
            acctDao.minusBalance(userId, transferType, money, redPackId.toString(), "TT101", busiType);
            return true;
        });

    }
    */
    @Override
    public Long createLiveRedPack(Long userId, Long liveId, Integer num, BigDecimal money, String title, String effTime) {
        AtomicReference<Long> redPack = new AtomicReference<>();
        Db.tx(() -> {

            //判断余额是否足够
            Acct acct = acctDao.queryGAcct(userId);
            if (acct.getBalanceFee().compareTo(money) < 0) {
                BizUtil.exception(Bizs.ERROR_BALANCE_LESS);
            }

            SysParam liveRedpParam = sysParamDao.findByCode(SysParam.LIVE_REDP_HANDLE_FEE_RATIO);

            //需要直接扣除50%的手续费
            BigDecimal handleMoney = money.multiply(new BigDecimal(liveRedpParam.getParamValue())).setScale(2);
            BigDecimal mixMoney = money.subtract(handleMoney);

            Long redPackId = null;
            try {
                redPackId = redPackDao.saveLiveRedPack(userId, liveId, num, mixMoney, title, effTime);
            } catch (ParseException e) {
                e.printStackTrace();
                BizUtil.exception("操作失败");
            }
            // 生成随机金额，目前取平均
//            BigDecimal avg = money.divide(BigDecimal.valueOf(num), 2, BigDecimal.ROUND_HALF_UP);
            List<BigDecimal> redPackMoney = PkgUtil.divide(mixMoney, num);

            String topic = "redpack_" + redPackId;
            SimpleQueue simpleQueue = simpleQueueFactory.getQueue(topic);

            for (BigDecimal sub : redPackMoney) {
                simpleQueue.offer(sub);
            }

            SysParam sysParam = sysParamDao.findByCode(SysParam.LIVE_RED_PACK_MINUTE_TIME);

            //日志记录
            String packType = "2";
            String changeType = "2";
            String tradeName = "直播红包-发给粉丝";
            redPackLogEao.save(redPackId, userId, packType, changeType, mixMoney, redPackId.toString(), AcctTradeType.SEND_LIVE_RED_PACK, tradeName);

            // 扣果子
            String transferType = "G";
            acctDao.minusBalance(userId, transferType, money, redPackId.toString(), AcctTradeType.SEND_LIVE_RED_PACK, BusiType.SEND_LIVE_RED_PACK);

            //记录es日志
            acctLogEao.save(UuidUtil.get(), acct.getAcctId(), userId, transferType, money,
                    Acct.FEE_IN_DE_MINUS, redPackId.toString(), AcctTradeType.SEND_LIVE_RED_PACK, tradeName,
                    BusiType.SEND_LIVE_RED_PACK, new Date());

            liveStatMao.sendRedPack(liveId, redPackId, DateUtil.addMinute(new Date(), Integer.parseInt(sysParam.getParamValue())).getTime());
            redPack.set(redPackId);

            //更新红包统计数据
            userExtDao.incTotalSendPack(userId, num);
            userExtDao.incSumSendPack(userId, money);
            return true;
        });

        return redPack.get();
    }

    @Override
    public Long createPersonRedPack(Long userId, Long otherId, BigDecimal money, String title) {
        AtomicReference<Long> redPack = new AtomicReference<>();
        boolean flag = Db.tx(() -> {
            //判断余额是否足够
            Acct acct = acctDao.queryGAcct(userId);
            if (acct.getBalanceFee().compareTo(money) < 0) {
                BizUtil.exception(Bizs.ERROR_BALANCE_LESS);
            }

            SysParam liveRedpParam = sysParamDao.findByCode(SysParam.PERSON_REDP_HANDLE_FEE_RATIO);

            //需要直接扣除50%的手续费
            BigDecimal handleMoney = money.multiply(new BigDecimal(liveRedpParam.getParamValue())).setScale(2);
            BigDecimal mixMoney = money.subtract(handleMoney).setScale(2);

            Long tradeId = redPackDao.savePersonRedPack(userId, otherId, mixMoney, title);
            //日志记录
            User other = userDao.getById(otherId);
            String packType = "2";
            String changeType = "1";
            String tradeName = "普通红包-发给" + other.getNickName();

            redPackLogEao.save(tradeId, userId, packType, changeType, mixMoney, tradeId.toString(), AcctTradeType.SEND_PERSON_RED_PACK, tradeName);
            //redPackDao.addRedPackLog(userId, packType, changeType, money, tradeId.toString(), tradeType, tradeName);
            // 扣果子
            String transferType = "G";

            acctDao.minusBalance(userId, transferType, money, tradeId.toString(), AcctTradeType.SEND_PERSON_RED_PACK, BusiType.SEND_PERSON_RED_PACK);

            //记录es日志
            acctLogEao.save(UuidUtil.get(), acct.getAcctId(), userId, transferType, money,
                    Acct.FEE_IN_DE_MINUS, tradeId.toString(), AcctTradeType.SEND_PERSON_RED_PACK, tradeName,
                    BusiType.SEND_PERSON_RED_PACK, new Date());

            redPack.set(tradeId);

            //更新红包统计数据
            userExtDao.incTotalSendPack(userId, 1);
            userExtDao.incSumSendPack(userId, money);
            return true;
        });

        if (!flag) {
            BizUtil.exception("操作失败");
        }

        return redPack.get();
    }

    @Override
    public Double recvRedPack(Long userId, Long redPackId) {
        AtomicReference<Double> redMoney = new AtomicReference<>();
        boolean flag = Db.tx(() -> {
            RedPackPerson pack = redPackDao.getPerRedPack(redPackId);
            if (pack == null) {
                BizUtil.exception("红包数据异常");
            }
            // 收红包
            redPackDao.updatePerRedPackStatus(pack, RedPackPerson.STATUS_RECVD);
            //日志记录
            User user = userDao.getById(pack.getFromUserId());
            String packType = "1";
            String changeType = "1";
            BigDecimal money = pack.getMoney();
            String tradeId = pack.getRedPackId().toString();

            String tradeName = "普通红包-来自" + user.getNickName();
            //redPackDao.addRedPackLog(userId, packType, changeType, money, tradeId.toString(), tradeType, tradeName);
            redPackLogEao.save(redPackId, userId, packType, changeType, money, tradeId.toString(), AcctTradeType.RECE_PERSON_RED_PACK, tradeName);

            // 加果子
            String transferType = "G";
            acctDao.addBalance(userId, transferType, money, tradeId.toString(), AcctTradeType.RECE_PERSON_RED_PACK, BusiType.RECEIVE_PERSON_RED_PACK);

            Acct acct = acctDao.queryGAcct(userId);

            //记录es日志
            acctLogEao.save(UuidUtil.get(), acct.getAcctId(), userId, transferType, money,
                    Acct.FEE_IN_DE_ADD, tradeId.toString(), AcctTradeType.RECE_PERSON_RED_PACK, tradeName,
                    BusiType.RECEIVE_PERSON_RED_PACK, new Date());

            //更新红包统计数据
            userExtDao.incTotalRecvPack(userId, 1);
            userExtDao.incSumRecvPack(userId, money);

            redMoney.set(money.doubleValue());
            return true;
        });

        if (!flag) {
            BizUtil.exception("操作失败");
        }

        return redMoney.get();

    }

    @Override
    public Double takeRedPack(Long userId, Long redPackId) {
        AtomicReference<Double> redMoney = new AtomicReference<>();
        boolean flag = Db.tx(() -> {
            CmfLiveRedPack pack = redPackDao.getLiveRedPack(redPackId);
            if (pack == null) {
                BizUtil.exception("红包数据异常");
            }

            if (pack.getEffTime().getTime() > new Date().getTime()) {
                BizUtil.exception("还没到抢红包时间");
            }

            LiveRedPackSubEo eo = liveRedPackSubEao.queryOne(redPackId, userId);
            if (eo != null) {
                BizUtil.exception("已经领取过该红包了");
            }

            String topic = "redpack_" + redPackId;
            SimpleQueue simpleQueue = simpleQueueFactory.getQueue(topic);
            //取出一个红包
            BigDecimal money = (BigDecimal) simpleQueue.poll();
            if (money == null) {
                BizUtil.exception("红包领取完了");
            }

            String tradeId = liveRedPackSubEao.save(redPackId, pack.getLiveId(), pack.getFromUserId(),
                    userId, pack.getMoney(), money, new Date());

            // 红包改剩余额度，剩余个数
            BigDecimal surplus = pack.getSurplus();
            surplus = surplus.subtract(money);
            /*
            if (!BigDecimalUtl.isGreaterThanZero(surplus)) {
                BizUtil.exception("红包领取异常");
            }*/
            redPackDao.updateLiveRedPackSurplus(pack, surplus);
            if (pack.getRestNum() - 1 <= 0) {
                redPackDao.updateLiveRedPackStatus(pack, "4");
            }
            //日志记录
            User user = userDao.getById(pack.getFromUserId());
            String packType = "1";
            String changeType = "2";
            String tradeName = "直播红包-来自" + user.getNickName();
            redPackLogEao.save(redPackId, userId, packType, changeType, money, tradeId, AcctTradeType.RECE_LIVE_RED_PACK, tradeName);
            // 加果子
            String transferType = "G";
            acctDao.addBalance(userId, transferType, money, tradeId.toString(), AcctTradeType.RECE_LIVE_RED_PACK, BusiType.TAKE_LIVE_RED_PACK);

            Acct acct = acctDao.queryGAcct(userId);
            //记录es日志
            acctLogEao.save(UuidUtil.get(), acct.getAcctId(), userId, transferType, money,
                    Acct.FEE_IN_DE_ADD, tradeId.toString(), AcctTradeType.RECE_LIVE_RED_PACK, tradeName,
                    BusiType.TAKE_LIVE_RED_PACK, new Date());


            //更新红包统计数据
            userExtDao.incTotalRecvPack(userId, 1);
            userExtDao.incSumRecvPack(userId, money);

            redMoney.set(money.doubleValue());
            return true;
        });

        return redMoney.get();
    }


    @Override
    public Page<RedPackLogEo> listLog(Long userId, Integer page, Integer limit) {
        return redPackLogEao.listLog(userId, page, limit);
    }

    @Override
    public CmfLiveRedPack queryLatestLivePack(Long liveId) {
        return redPackDao.queryLatestLivePack(liveId);
    }

    @Override
    public Page<RedPackLogEo> listRecieveLogById(Long redPackId, String changeType, Integer page, Integer limit) {
        return redPackLogEao.listRecieveLogById(redPackId, changeType, page, limit);
    }

    @Override
    public RedPackLogEo queryPersonRecieve(Long redPackId, Long userId) {
        return redPackLogEao.queryPersonRecieve(redPackId, userId);
    }

    @Override
    public Page<RedPackLogEo> listPersonSendPack(Long fromUserId, Integer page, Integer limit) {
        return redPackLogEao.listPersonSendPack(fromUserId, page, limit);
    }

    @Override
    public RedPackDetailsVo RedPackDetails(Long redId, String tradeType) {
        RedPackDetailsVo vo = new RedPackDetailsVo();
        //直播红包
        if (AcctTradeType.SEND_LIVE_RED_PACK.equals(tradeType)
                || AcctTradeType.RECE_LIVE_RED_PACK.equals(tradeType)
                || AcctTradeType.RETURN_LIVE_RED_PACK.equals(tradeType)) {
            CmfLiveRedPack cmfLiveRedPack = redPackDao.getCmfLiveRedPack(redId, tradeType);
            if (cmfLiveRedPack != null) {
                vo.setMoney(cmfLiveRedPack.getMoney().setScale(2, BigDecimal.ROUND_HALF_UP));
                vo.setRedPackId(cmfLiveRedPack.getRedPackId());
                vo.setRemark(cmfLiveRedPack.getRemark());
                if (cmfLiveRedPack.getSendTime() != null) {
                    vo.setSendTime(com.cssw.fyzb.core.util.DateUtil.format(cmfLiveRedPack.getSendTime()));
                }
                vo.setStatus(cmfLiveRedPack.getStatus());
                vo.setTitle(cmfLiveRedPack.getTitle());
                vo.setUserId(cmfLiveRedPack.getFromUserId());
                vo.setReceiveNum(cmfLiveRedPack.getReceiveNum());
                vo.setNum(cmfLiveRedPack.getNum());

                //List<CmfLiveRedPackSub> sub = redPackDao.listUser(redId);
                //changeType 红包类型(1-私人红包 2-直播间红包)
                Page<RedPackLogEo> page = redPackLogEao.listRecieveLogById(redId, "2", 1, cmfLiveRedPack.getNum());
                List<RedPackUser> list = new ArrayList<>();
                RedPackUser redPackUser = null;
                int restNum = 0;
                if (page.getList() != null) {
                    User user = null;
                    for (RedPackLogEo s : page.getList()) {
                        if (!s.getUserId().equals(cmfLiveRedPack.getFromUserId())) {
                            redPackUser = new RedPackUser();
                            user = userDao.getById(s.getUserId());
                            redPackUser.setMoney(s.getMoney().setScale(2, BigDecimal.ROUND_DOWN));
                            if (null != user) {
                                redPackUser.setName(user.getNickName());
                            }
                            redPackUser.setUserId(s.getUserId());
                            redPackUser.setReceiveTime(s.getCreateTime());

                            restNum = restNum + 1;
                            list.add(redPackUser);
                        }
                    }
                }
                vo.setRestNum(restNum);
                vo.setList(list);
            }
        } else if (AcctTradeType.SEND_PERSON_RED_PACK.equals(tradeType)
                || AcctTradeType.RECE_PERSON_RED_PACK.equals(tradeType)
                || AcctTradeType.RETURN_PERSON_RED_PACK.equals(tradeType)) {
            RedPackPerson cmfLiveRedPack = redPackDao.getPerRedPack(redId);
            vo.setMoney(cmfLiveRedPack.getMoney().setScale(2, BigDecimal.ROUND_HALF_UP));
            vo.setRedPackId(cmfLiveRedPack.getRedPackId());
            vo.setRemark(cmfLiveRedPack.getRemark());
            if (cmfLiveRedPack.getSendTime() != null) {
                vo.setSendTime(com.cssw.fyzb.core.util.DateUtil.format(cmfLiveRedPack.getSendTime()));
            }
            vo.setStatus(cmfLiveRedPack.getStatus());
            vo.setTitle(cmfLiveRedPack.getTitle());
            vo.setUserId(cmfLiveRedPack.getFromUserId());
            vo.setNum(1);
            //领取
            if ("2".equals(cmfLiveRedPack.getStatus())) {
                //已领取红包个数
                vo.setReceiveNum(1);
                //剩余
                vo.setRestNum(0);
            } else {
                vo.setReceiveNum(0);
                vo.setRestNum(1);
            }
            //List<CmfLiveRedPackSub> sub = redPackDao.listUser(redId);
            //changeType 红包类型(1-私人红包 2-直播间红包)
            Page<RedPackLogEo> page = redPackLogEao.listRecieveLogById(redId, "1", 1, 1);
            List<RedPackUser> list = new ArrayList<>();
            RedPackUser redPackUser = null;
            if (page.getList() != null) {
                User user = null;
                for (RedPackLogEo s : page.getList()) {
                    redPackUser = new RedPackUser();
                    user = userDao.getById(s.getUserId());
                    redPackUser.setMoney(s.getMoney().setScale(2, BigDecimal.ROUND_DOWN));
                    if (null != user) {
                        redPackUser.setName(user.getNickName());
                    }
                    redPackUser.setUserId(s.getUserId());
                    redPackUser.setReceiveTime(s.getCreateTime());
                    list.add(redPackUser);
                }
            }
            vo.setList(list);
        }
        return vo;
    }
}
